using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

[SerializeField]
public class Mortal : SynchronizedGameObject, ICanUseWeapon, IDamagable, IKillable
{
	public const int DefaultMortalHeight = 3;

	public KillInfo lastDamageInfo;

	public int lastKillerID;

	[SerializeField]
	private List<DamageTypeMultiplier> damageMultiplier;

	private bool _isDead;

	[SerializeField]
	private int _health = 100;

	private SaveInt saveHealth;

	[SerializeField]
	private int _maxHealth = 100;

	[SerializePrivateVariables]
	private int _armor;

	private SaveInt saveArmor;

	public int _maxArmor;

	private SaveInt saveMaxArmor;

	public bool isImmortal;

	private LinkedList<GameObject> countAttachedOnObject = new LinkedList<GameObject>();

	[SerializeField]
	private int _bodyHeight;

	private int damageAkumulator;

	private int damageTypeAkumulator;

	private Vector3 onlineHitPoint = Vector3.zero;

	private IEnumerator _sendOnline;

	protected bool isCriticalDamage;

	public bool isDead
	{
		get
		{
			return _isDead;
		}
		set
		{
			_isDead = value;
		}
	}

	public virtual int health
	{
		get
		{
			return saveHealth;
		}
		set
		{
			if (_health != value)
			{
				value = Mathf.Clamp(value, 0, maxHealth);
				saveHealth = value;
				_health = value;
			}
		}
	}

	public virtual int maxHealth
	{
		get
		{
			return _maxHealth;
		}
		set
		{
			_maxHealth = value;
		}
	}

	public virtual int armor
	{
		get
		{
			return saveArmor;
		}
		set
		{
			if (armor != value)
			{
				value = Mathf.Clamp(value, 0, maxArmor);
				_armor = value;
				saveArmor = value;
			}
		}
	}

	public virtual int maxArmor
	{
		get
		{
			return saveMaxArmor;
		}
		set
		{
			saveMaxArmor = value;
			_maxArmor = value;
		}
	}

	public int BodyHeight
	{
		get
		{
			return _bodyHeight;
		}
	}

	public void ResetLastDamageInfo(WeaponType weaponType, WeaponTypeSpecific weaponTypeSpecific, int playerID, float timeFromRespawn, float distance, bool headshot, bool invisible, bool victimJetpack, bool killerJetpack, bool isChating, bool sniperMod)
	{
		lastDamageInfo.time = 0f;
		lastDamageInfo.weaponType = weaponType;
		lastDamageInfo.weaponTypeSpecific = weaponTypeSpecific;
		lastDamageInfo.distance = distance;
		lastDamageInfo.playerID = playerID;
		lastDamageInfo.timeOfRespawn = timeFromRespawn;
		lastDamageInfo.headshot = headshot;
		lastDamageInfo.invisible = invisible;
		lastDamageInfo.victimJetpack = victimJetpack;
		lastDamageInfo.killerJetpack = killerJetpack;
		lastDamageInfo.isChating = isChating;
		lastDamageInfo.sniperMod = sniperMod;
	}

	public virtual void AddWeaponEffect(int effectType, int damageType, float effectDuration, float effectPower, int killerID)
	{
	}

	public virtual void FullHealthAndArmor()
	{
		health = maxHealth;
		armor = maxArmor;
	}

	public virtual int GetBodyHeight()
	{
		return (BodyHeight != 0) ? BodyHeight : 3;
	}

	[PunRPC]
	public virtual void GetDamage(int damage, int damageType)
	{
		GetDamage(damage, damageType, -99999);
	}

	[PunRPC]
	public virtual void GetDamage(int damage, int damageType, int idKiller)
	{
		GetDamage(damage, damageType, idKiller, Vector3.zero);
	}

	private IEnumerator SendOnline()
	{
		while (true)
		{
			if (damageAkumulator > 0)
			{
				if (base.viewId != PlayerBehavior.MyPlayer.viewId)
				{
					base.photonView.RPC("GetDamage", PhotonTargets.Others, damageAkumulator, damageTypeAkumulator, PlayerBehavior.MyPlayer.viewId, Vector3.zero, isCriticalDamage, onlineHitPoint);
					onlineHitPoint = Vector3.zero;
				}
				damageAkumulator = 0;
				damageTypeAkumulator = 0;
			}
			yield return new WaitForSeconds(0.5f);
		}
	}

	[PunRPC]
	public virtual void GetDamage(int damage, int damageType, int iKillerId, Vector3 positionKiller, bool criticalDamage, Vector3? hitPoint = null)
	{
		isCriticalDamage = criticalDamage;
		GetDamage(damage, damageType, iKillerId, positionKiller, hitPoint);
	}

	[PunRPC]
	public virtual void GetDamage(int damage, int damageType, int iKillerId, Vector3 positionKiller, Vector3? hitPoint = null)
	{
		if (((GameController.instance.curTypeGame == TypeGame.RocketLeague || !GameController.instance.CanDeadInGame()) && GameController.instance.curTypeGame != TypeGame.CopsAndRobbers) || isDead || isImmortal)
		{
			return;
		}
		if (!settings.offlineMode && iKillerId == PlayerBehavior.MyPlayer.viewId)
		{
			damageAkumulator += damage;
			damageTypeAkumulator = damageType;
			if (hitPoint.HasValue)
			{
				onlineHitPoint = hitPoint.Value;
			}
			if (_sendOnline == null)
			{
				_sendOnline = SendOnline();
				CoroutineRunner.Instance.StartCoroutine(_sendOnline);
			}
			if (PlayerBehavior.MyPlayer.currentCar != null && PlayerBehavior.MyPlayer.currentCar is TitanBehavior && TitanControlls.instance != null)
			{
				TitanfallControllerUI.instance.HitAnimation();
			}
			if (GameController.instance.curTypeGame == TypeGame.TitanfallV2)
			{
				int num = ((damage <= 500) ? damage : 500);
				if (this is EntityBehavior && !((EntityBehavior)this).isFree)
				{
					TitanSpawner.instance.titanSpawnRecharge += (float)num * TitanSpawner.instance.damagePointsMuliplaer;
				}
				if (this is PlayerBehavior)
				{
					TitanSpawner.instance.titanSpawnRecharge += (float)num * TitanSpawner.instance.damagePointsMuliplaer;
				}
			}
		}
		damage = ApplyDamageTypeMultiplier(damage, (DamageType)damageType);
		if (!hitPoint.HasValue)
		{
			hitPoint = positionKiller;
		}
		damage = UpdateDamageAccordingToHitPoint(damage, hitPoint.Value);
		int num2 = armor - damage;
		if (num2 < 0 && armor > 0)
		{
			armor = 0;
		}
		if (num2 < 0)
		{
			health += num2;
		}
		else
		{
			armor -= damage;
		}
		if (health <= 0 && damage > 0)
		{
			ShowKill((DamageType)damageType);
			Kill(iKillerId);
		}
		if (base.isMine && (ownerPhotonView != null || PlayerBehavior.MyPlayer == this) && damage > 0 && (damageType != 1 || !PlayerBehavior.MyPlayer.inCar))
		{
			float? num3 = 0f;
			num3 = ((!(positionKiller != Vector3.zero)) ? HitMarks.instance.RotateDamage(iKillerId) : HitMarks.instance.RotateDamage(positionKiller));
			HitMarks.instance.ShowHit(num3, damage);
			HitMarks.instance.ShowStartHit(num3, damage, positionKiller);
			if (GameController.instance.curTypeGame == TypeGame.TitanfallV2)
			{
				int num4 = ((damage <= 500) ? damage : 500);
				if (this is PlayerBehavior)
				{
					TitanSpawner.instance.titanSpawnRecharge += (float)num4 * TitanSpawner.instance.myDamagePointsMuliplaer;
				}
			}
		}
		if (GameController.instance.curTypeGame == TypeGame.tanks && PlayerBehavior.MyPlayer.photonView.viewID == iKillerId && PlayerBehavior.MyPlayer != this && PlayerBehavior.MyPlayer.currentCar != null && !(PlayerBehavior.MyPlayer.currentCar != this))
		{
		}
	}

	public bool CheckDead(int damage, int damageType)
	{
		return ApplyDamageTypeMultiplier(damage, (DamageType)damageType) > armor + health;
	}

	public int UpdateDamageAccordingToHitPoint(int givenDamage, Vector3 hitPosition)
	{
		CarBehavior carBehavior = this as CarBehavior;
		if (carBehavior == null)
		{
			return givenDamage;
		}
		EntityBehavior.ColliderMultiplier colliderMultiplier = carBehavior.damageMultiplyingColliders.FirstOrDefault((EntityBehavior.ColliderMultiplier x) => x.collider.bounds.Contains(hitPosition));
		if (colliderMultiplier == null)
		{
			return givenDamage;
		}
		BCWDebug.Log(string.Format("Multipluer equals {0:f2} for {1}.", colliderMultiplier.multiplier, colliderMultiplier.collider.name));
		return Mathf.RoundToInt((float)givenDamage * colliderMultiplier.multiplier);
	}

	public int ApplyDamageTypeMultiplier(int damage, DamageType damageType)
	{
		if (damageMultiplier != null)
		{
			int num = damageMultiplier.FindIndex((DamageTypeMultiplier m) => m.type == damageType);
			if (num >= 0)
			{
				return (int)(damageMultiplier[num].value * (float)damage);
			}
		}
		return damage;
	}

	public override void Awake()
	{
		base.Awake();
		saveHealth = _health;
		saveArmor = _armor;
		saveMaxArmor = _maxArmor;
		if (base.photonView != null && base.photonView.owner != PhotonNetwork.player)
		{
			TitanTargetDetector.InsertToTargetList(this);
			WeaponTargetDetector.InsertToTargetList(this);
		}
		else if (settings.offlineMode)
		{
			WeaponTargetDetector.InsertToTargetList(this);
		}
	}

	public override void Start()
	{
		base.Start();
		ResetLastDamageInfo(WeaponType.Non, WeaponTypeSpecific.Non, 0, -1f, 0f, false, false, false, false, false, false);
	}

	[PunRPC]
	public virtual void Kill(int iKillerId = -9999)
	{
		if (GameController.instance.curTypeGame == TypeGame.RocketLeague || !GameController.instance.CanDeadInGame() || isDead)
		{
			return;
		}
		isDead = true;
		health = 0;
		armor = 0;
		if (!settings.offlineMode)
		{
			if (base.photonView.isMine && !base.photonView.isSceneView)
			{
				lastKillerID = iKillerId;
				base.photonView.RPC("Kill", PhotonTargets.Others, iKillerId);
			}
			else if (iKillerId == PlayerBehavior.MyPlayer.viewId)
			{
				base.photonView.RPC("Kill", PhotonPlayer.Find(base.ownerId), iKillerId);
			}
		}
		if ((settings.offlineMode && GameController.instance.playerScript != this) || (iKillerId == GameController.instance.playerScript.viewId && GameController.instance.playerScript != this))
		{
			WalkWindow.instance.aimHUD.ShowAimDead();
			if (GameController.instance.curTypeGame == TypeGame.TitanfallV2 && this is PlayerBehavior)
			{
				TitanSpawner.instance.titanSpawnRecharge += TitanSpawner.instance.killPoints;
			}
		}
	}

	public virtual void ShowKill(DamageType damage)
	{
	}

	public virtual void Respawn()
	{
		Respawn(Vector3.zero);
	}

	public virtual void Respawn(Vector3 position)
	{
		if (!settings.offlineMode)
		{
			ToggleTeleportParam();
			if (GameController.instance.curTypeGame == TypeGame.CopsAndRobbers)
			{
				ToggleTeleportParam(1.5f);
			}
		}
		FullHealthAndArmor();
		if (GameController.instance.curTypeGame != TypeGame.tanks && GameController.instance.curTypeGame != TypeGame.WalkingRobots)
		{
			Invoke("WaitDead", 1f);
		}
		else
		{
			isDead = false;
		}
		OnChargeObj[] componentsInChildren = GetComponentsInChildren<OnChargeObj>();
		if (componentsInChildren != null)
		{
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				PhotonView component = componentsInChildren[i].GetComponent<PhotonView>();
				if (component != null)
				{
					if (component.isMine)
					{
						PhotonNetwork.Destroy(componentsInChildren[i].gameObject);
					}
				}
				else
				{
					Object.Destroy(componentsInChildren[i].gameObject);
				}
			}
		}
		base.transform.parent = null;
		base.transform.position = position;
		base.transform.eulerAngles = Vector3.zero;
	}

	private void WaitDead()
	{
		isDead = false;
		if (GameController.instance.playerScript != null)
		{
			GameController.instance.playerScript.ActivateJetpack();
		}
	}

	[PunRPC]
	public void AttachArrow(string objName, Vector3 pos, Quaternion rotation, string arrowName)
	{
		GameObject gameObject = Object.Instantiate(Resources.Load("Grenade/" + arrowName)) as GameObject;
		gameObject.GetComponent<Rigidbody>().useGravity = false;
		RemoveAllComponnents(gameObject);
		Transform[] componentsInChildren = GetComponentsInChildren<Transform>();
		foreach (Transform transform in componentsInChildren)
		{
			if (transform.name == objName)
			{
				gameObject.transform.parent = base.gameObject.transform;
				gameObject.transform.position = pos;
				gameObject.transform.rotation = rotation;
				Object.Destroy(gameObject, 15f);
			}
		}
		countAttachedOnObject.AddLast(gameObject);
		if (countAttachedOnObject.Count > 9)
		{
			if (countAttachedOnObject.First.Value != null)
			{
				Object.Destroy(countAttachedOnObject.First.Value);
				countAttachedOnObject.RemoveFirst();
			}
			else
			{
				countAttachedOnObject.RemoveFirst();
			}
		}
	}

	public virtual void ShowNormalDamage()
	{
		isCriticalDamage = false;
	}

	public virtual void ShowCriticalDamage()
	{
		isCriticalDamage = true;
	}

	public virtual void GetOutOfCar(bool withAnim)
	{
	}

	public void RemoveAllComponnents(GameObject obj)
	{
		MonoBehaviour[] components = obj.GetComponents<MonoBehaviour>();
		foreach (MonoBehaviour monoBehaviour in components)
		{
			if (monoBehaviour.GetType() != typeof(OnChargeArrow))
			{
				Object.Destroy(monoBehaviour);
			}
		}
		obj.GetComponent<Rigidbody>().isKinematic = true;
		Object.Destroy(obj.GetComponent<Collider>());
		Object.Destroy(obj.GetComponent<TrailRenderer>());
		Object.Destroy(obj.GetComponent<AudioSource>());
	}

	public void ClearDamageMultiplier()
	{
		damageMultiplier.Clear();
	}

	public virtual Vector3 GetPositionForChargeHit()
	{
		return base.transform.position;
	}

	public void AddDamageMultiplier(DamageTypeMultiplier multiplier)
	{
		int num = damageMultiplier.FindIndex((DamageTypeMultiplier m) => m.type == multiplier.type);
		if (num >= 0)
		{
			DamageTypeMultiplier value = damageMultiplier[num];
			value.value *= multiplier.value;
			damageMultiplier[num] = value;
		}
		else
		{
			damageMultiplier.Add(multiplier);
		}
	}
}
